Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

565
Visualizações
Bash: cómo imprimir y ejecutar una matriz cmd que tiene el operador de tubería, |, en ella

Este es un seguimiento de mi pregunta aquí: Cómo escribir la función bash para imprimir y ejecutar el comando cuando el comando tiene argumentos con espacios o cosas para expandir

Supongamos que tengo esta función para imprimir y ejecutar un comando almacenado en una matriz:

 # Print and run the cmd stored in the passed-in array print_and_run() { echo "Running cmd: $*" # run the command by calling all elements of the command array at once "$@" }

Esto funciona bien:

 cmd_array=(ls -a /) print_and_run "${cmd_array[@]}"

Pero esto no funciona:

 cmd_array=(ls -a / | grep "home") print_and_run "${cmd_array[@]}"

Error: syntax error near unexpected token `|' :

 eRCaGuy_hello_world/bash$ ./print_and_run.sh ./print_and_run.sh: line 55: syntax error near unexpected token `|' ./print_and_run.sh: line 55: `cmd_array=(ls -a / | grep "home")'

¿Cómo puedo hacer que este concepto funcione con el operador de tubería ( | ) en el comando?

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

Si desea tratar un elemento de matriz que contiene solo | como una instrucción para generar una canalización, puede hacerlo. No lo recomiendo , significa que tiene un riesgo de seguridad si no verifica que las variables en su cadena no pueden consistir solo en un solo carácter de canalización, pero es posible.

A continuación, creamos un sigilo aleatorio "$pipe" de un solo uso para que el ataque sea más difícil. Si no está dispuesto a hacer eso, cambie [[ $arg = "$pipe" ]] a [[ $arg = "|" ]] .

 # generate something random to make an attacker's job harder pipe=$(uuidgen) # use that randomly-generated sigil in place of | in our array cmd_array=( ls -a / "$pipe" grep "home" ) exec_array_pipe() { local arg cmd_q local -a cmd=( ) while (( $# )); do arg=$1; shift if [[ $arg = "$pipe" ]]; then # log an eval-safe copy of what we're about to run printf -v cmd_q '%q ' "${cmd[@]}" echo "Starting pipeline component: $cmd_q" >&2 # Recurse into a new copy of ourselves as a child process "${cmd[@]}" | exec_array_pipe "$@" return fi cmd+=( "$arg" ) done printf -v cmd_q '%q ' "${cmd[@]}" echo "Starting pipeline component: $cmd_q" >&2 "${cmd[@]}" } exec_array_pipe "${cmd_array[@]}"

Vea esto ejecutándose en un entorno limitado en línea en https://ideone.com/IWOTfO

over 4 years ago · Santiago Trujillo Relatório

0

La dirección general es que no. No almacena toda la línea de comando para imprimirla más tarde, y esta no es la dirección que debe tomar.

La solución "mala" es usar eval .

La solución "buena" es almacenar el literal '|' carácter dentro de la matriz (o alguna mejor representación de la misma) y analice la matriz, extraiga las partes de la tubería y ejecútelas. Esto lo presenta Charles en la otra respuesta asombrosa. Simplemente está reescribiendo el analizador que ya existe en el shell. Requiere un trabajo significativo, y expandirlo requerirá un trabajo significativo.

El resultado final es que está reimplementando partes de shell dentro de shell. Básicamente escribiendo un intérprete de shell en shell. En este punto, puede considerar tomar las fuentes de Bash e implementar una nueva opción shopt -o print_the_command_before_executing en las fuentes, que podría ser más simple.

Sin embargo, creo que el objetivo final es brindar a los usuarios una forma de ver lo que se está ejecutando. Propondría abordarlo como lo hace .gitlab-ci.yml con script: declaraciones. Si desea inventar su propio lenguaje con soporte de "depuración", hágalo en lugar de medias tintas. Considere el siguiente archivo YAML:

 - ls -a / | grep "home" - echo other commands - for i in "stuff"; do echo "$i"; done - | for i in "stuff"; do echo "$i" done

Luego el siguiente "corredor":

 import yaml import shlex import os import sys script = [] input = yaml.safe_load(open(sys.argv[1], "r")) for line in input: script += [ "echo + " + shlex.quote(line).replace("\n", "<newline>"), # some unicode like ␤ would look nice line, ] os.execvp("bash", ["bash", "-c", "\n".join(script)])

Ejecutar el corredor da como resultado:

 + ls -a / | grep "home" home + echo other commands other commands + for i in "stuff"; do echo "$i"; done stuff + for i in "stuff"; do<newline> echo "$i"<newline>done<newline> stuff

Esto ofrece una mayor flexibilidad y es bastante simple, admite cualquier construcción de caparazón con facilidad. Puede probar gitlab-ci/cd en su repositorio y leer los documentos .

El formato YAML es solo un ejemplo del formato de entrada. El uso de comentarios especiales como # --- cut --- entre partes y la extracción de cada parte con el analizador permitirá ejecutar shellcheck sobre el script. En lugar de generar un script con declaraciones de echo , puede ejecutar Bash de forma interactiva, imprimir la parte que se ejecutará y luego "alimentar" la parte que se ejecutará a Bash interactivo. ¿Esto permitirá conservar $? .

De cualquier manera, con una solución "buena", terminas con un analizador personalizado.

over 4 years ago · Santiago Trujillo Relatório

0

Haz esto en su lugar. Funciona.

 print_and_run() { echo "Running cmd: $1" eval "$1" }

Ejemplo de uso:

 cmd='ls -a / | grep -C 9999 --color=always "home"' print_and_run "$cmd"

Producción:

 Running cmd: ls -a / | grep -C 9999 --color=always "home" (rest of output here, with the word "home" highlighted in red)
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda